var util = {
  css: function(elem, obj) {
    for (var i in obj) {
      elem.style[i] = obj[i]
    }
  },
  hasClass: function(elem, classN) {
    var className = elem.getAttribute('class')
    return className.indexOf(classN) !== -1
  }
}

function Colorpicker(opt) {
  if (this === window) {
    throw `Colorpicker: Can't call a function directly`
  }
  this.init(opt)
}

Colorpicker.prototype = {
  init(opt) {
    const { el, initColor = 'rgb(255,0,0)', allMode = ['hex', 'rgb'], color = '' } = opt
    var elem = el // document.getElementById(el)

    if (!(elem && elem.nodeType && elem.nodeType === 1)) {
      throw `Colorpicker: not found  ID:${el}  HTMLElement,not ${{}.toString.call(el)}`
    }

    this.Opt = {
      ...opt,
      el,
      initColor,
      allMode,
      color
    }

    this.bindElem = elem // 绑定的元素
    this.elem_wrap = null // 最外层容器
    this.fixedBg = null // 拾色器后面固定定位的透明div 用于点击隐藏拾色器
    this.elem_colorPancel = null // 色彩面板
    this.elem_picker = null // 拾色器色块按钮
    this.elem_barPicker1 = null // 颜色条
    this.elem_hexInput = null // 显示hex的表单
    this.elem_showColor = null // 显示当前颜色

    this.pancelLeft = 0
    this.pancelTop = 0

    this.downX = 0
    this.downY = 0
    this.moveX = 0
    this.moveY = 0

    this.pointLeft = 0
    this.pointTop = 0

    this.rgba = { r: 0, g: 0, b: 0, a: 1 }
    this.hsb = { h: 0, s: 100, b: 100 }

    var _this = this; var rgb = initColor.slice(4, -1).split(',')

    this.rgba.r = parseInt(rgb[0])
    this.rgba.g = parseInt(rgb[1])
    this.rgba.b = parseInt(rgb[2])

    var body = document.getElementsByTagName('body')[0]
    var div = document.createElement('div')

    div.innerHTML = this.render()
    body.appendChild(div)

    this.elem_wrap = div
    this.fixedBg = div.children[0] // 遮罩层
    this.elem_colorPancel = div.getElementsByClassName('color-pancel')[0]
    this.pancel_width = this.elem_colorPancel.offsetWidth
    this.pancel_height = this.elem_colorPancel.offsetHeight
    this.elem_picker = div.getElementsByClassName('pickerBtn')[0]
    this.elem_showColor = div.getElementsByClassName('colorpicker-showColor')[0]
    this.elem_barPicker1 = div.getElementsByClassName('colorBar-color-picker')[0]
    this.elem_hexInput = div.getElementsByClassName('colorpicker-hexInput')[0]

    // var rect = this.bindElem.getBoundingClientRect();
    elem = this.bindElem
    var top = elem.offsetTop - 215
    var left = elem.offsetLeft + elem.clientWidth
    while (elem.offsetParent) {
      top += elem.offsetParent.offsetTop
      left += elem.offsetParent.offsetLeft
      elem = elem.offsetParent
    }

    this.pancelLeft = left
    this.pancelTop = top + this.bindElem.offsetHeight
    util.css(div, {
      'position': 'absolute',
      'z-index': 2,
      'display': 'none',
      'left': left + 'px',
      'top': top + this.bindElem.offsetHeight + 'px'
    })

    this.bindMove(this.elem_colorPancel, this.setPosition, true)
    this.bindMove(this.elem_barPicker1.parentNode, this.setBar, false)

    _this.show()

    /*
    // 点击绑定el打开拾色器
     this.bindElem.addEventListener('click', function() {
        _this.show()
      }, false) */

    this.fixedBg.addEventListener('click', function(e) {
      _this.hide()
    }, false)

    /* this.elem_wrap.addEventListener('input', function(e) {
      e.stopPropagation()
      var target = e.target; var value = target.value
      const mode = target.classList.contains('colorpicker-hexInput') ? 'hex' : 'rgb'
      _this.setColorByInput(value, mode)
    }, false); */

    const inputEls = this.elem_wrap.getElementsByTagName('input')
    for (const el of inputEls) {
      el.addEventListener('blur', function(e) {
        var target = e.target; var value = target.value
        if (util.hasClass(target, 'colorpicker-hexInput')) {
          _this.setColorByInput(value, 'hex')
        } else {
          _this.setColorByInput(value, 'rgb')
        }
      }, false)
    }

    (color !== '' && this.setColorByInput(color, 'hex'))
  },
  render: function() {
    var hex = '#' + this.rgbToHex(this.HSBToRGB(this.hsb))
    var tpl =
				`<div style="position: fixed; top: 0px; right: 0px; bottom: 0px; left: 0px;"></div>
				<div style="position: inherit;z-index: 100;display: flex;box-shadow: rgba(0, 0, 0, 0.3) 0px 0px 2px, rgba(0, 0, 0, 0.3) 0px 4px 8px;">
					<div class="colorpicker-pancel" style="background: rgb(255, 255, 255);box-sizing: initial; width: 225px; font-family: Menlo;">
						<div style="width: 100%; padding-bottom: 55%; position: relative; border-radius: 2px 2px 0px 0px; overflow: hidden;">
							<div class="color-pancel" style="position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px; background: rgb(${this.rgba.r},${this.rgba.g},${this.rgba.b})">
								<style>
									.saturation-white {background: -webkit-linear-gradient(to right, #fff, rgba(255,255,255,0));background: linear-gradient(to right, #fff, rgba(255,255,255,0));}
									.saturation-black {background: -webkit-linear-gradient(to top, #000, rgba(0,0,0,0));background: linear-gradient(to top, #000, rgba(0,0,0,0));}
								</style>
								<div class="saturation-white" style="position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px;">
									<div class="saturation-black" style="position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px;">
									</div>
									<div class="pickerBtn" style="position: absolute; top: 0%; left: 100%; cursor: default;">
										<div style="width: 12px; height: 12px; border-radius: 6px; box-shadow: rgb(255, 255, 255) 0px 0px 0px 1px inset; transform: translate(-6px, -6px);">
										</div>
									</div>
								</div>
							</div>
						</div>
						<div style="padding: 0 16px 20px;">
							<div class="flexbox-fix" style="display: flex;align-items: center;height: 40px;">
								<div style="width: 32px;">
									<div style="width: 16px; height: 16px; border-radius: 8px; position: relative; overflow: hidden;">
										<div class="colorpicker-showColor" style="position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px; border-radius: 8px; box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 0px 1px inset; background:rgb(${this.rgba.r},${this.rgba.g},${this.rgba.b}); z-index: 2;"></div>
										<div class="" style="position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px; background: url(&quot;&quot;) left center;"></div>
									</div>
								</div>
								<div style="-webkit-box-flex: 1; flex: 1 1 0%;"><div style="height: 10px; position: relative;">
									<div style="position: absolute; top: 0px;right: 0px; bottom: 0px; left: 0px;">
										<div class="hue-horizontal" style="padding: 0px 2px; position: relative; height: 100%;">
											<style>
												.hue-horizontal {background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);background: -webkit-linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);}
												.hue-vertical {background: linear-gradient(to top, #f00 0%, #ff0 17%, #0f0 33%,#0ff 50%, #00f 67%, #f0f 83%, #f00 100%);background: -webkit-linear-gradient(to top, #f00 0%, #ff0 17%,#0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);}
											</style>
											<div  class="colorBar-color-picker" style="position: absolute; left: 0%;">
												<div style="width: 12px; height: 12px; border-radius: 6px; transform: translate(-6px, -1px); background-color: rgb(248, 248, 248); box-shadow: rgba(0, 0, 0, 0.37) 0px 1px 4px 0px;">
												</div>
											</div>
										</div>
									</div>
								</div>
							</div>
						</div>
						<div class="flexbox-fix" style="display: flex;">
							<div class="flexbox-fix colorpicker-inputWrap" style="-webkit-box-flex: 1; flex: 1 1 0%; display: flex; margin-left: -6px;">
                
                <div style="padding-left: 6px; width: 150%;">
                  <div style="position: relative;">
                    <input class="colorpicker-hexInput" value="${hex}" spellcheck="false" style="font-size: 11px; color: rgb(51, 51, 51); width: 100%; border-radius: 2px; border: none; box-shadow: rgb(218, 218, 218) 0px 0px 0px 1px inset; height: 21px; text-align: center;">
                    <span style="text-transform: uppercase; font-size: 11px; line-height: 11px; color: rgb(150, 150, 150); text-align: center; display: block; margin-top: 12px;">hex</span>
                  </div>
                </div>
                <div style="padding-left: 6px; width: 100%;">
                  <div style="position: relative;">
                    <input class="colorpicker-rInput" value="${this.rgba.r}" spellcheck="false" style="font-size: 11px; color: rgb(51, 51, 51); width: 100%; border-radius: 2px; border: none; box-shadow: rgb(218, 218, 218) 0px 0px 0px 1px inset; height: 21px; text-align: center;">
                    <span style="text-transform: uppercase; font-size: 11px; line-height: 11px; color: rgb(150, 150, 150); text-align: center; display: block; margin-top: 12px;">R</span>
                  </div>
                </div>
                <div style="padding-left: 6px; width: 100%;">
                  <div style="position: relative;">
                    <input class="colorpicker-gInput" value="${this.rgba.g}" spellcheck="false" style="font-size: 11px; color: rgb(51, 51, 51); width: 100%; border-radius: 2px; border: none; box-shadow: rgb(218, 218, 218) 0px 0px 0px 1px inset; height: 21px; text-align: center;">
                    <span style="text-transform: uppercase; font-size: 11px; line-height: 11px; color: rgb(150, 150, 150); text-align: center; display: block; margin-top: 12px;">G</span>
                  </div>
                </div>
                <div style="padding-left: 6px; width: 100%;">
                  <div style="position: relative;">
                    <input class="colorpicker-bInput" value="${this.rgba.b}" spellcheck="false" style="font-size: 11px; color: rgb(51, 51, 51); width: 100%; border-radius: 2px; border: none; box-shadow: rgb(218, 218, 218) 0px 0px 0px 1px inset; height: 21px; text-align: center;">
                    <span style="text-transform: uppercase; font-size: 11px; line-height: 11px; color: rgb(150, 150, 150); text-align: center; display: block; margin-top: 12px;">B</span>
                  </div>
                </div>


							</div>
						</div>
					</div>
				</div>
			</div>`
    return tpl
  },
  getInputTpl: function() {
    var current_mode_html = ''
    var hex = '#' + this.rgbToHex(this.HSBToRGB(this.hsb))
    current_mode_html += `
        <div style="padding-left: 6px; width: 150%;">
          <div style="position: relative;">
            <input class="colorpicker-hexInput" value="${hex}" spellcheck="false" style="font-size: 11px; color: rgb(51, 51, 51); width: 100%; border-radius: 2px; border: none; box-shadow: rgb(218, 218, 218) 0px 0px 0px 1px inset; height: 21px; text-align: center;">
            <span style="text-transform: uppercase; font-size: 11px; line-height: 11px; color: rgb(150, 150, 150); text-align: center; display: block; margin-top: 12px;">hex</span>
          </div>
        </div>`

    for (var i = 0; i < 3; i++) {
      current_mode_html +=
        `<div style="padding-left: 6px; width: 100%;">
          <div style="position: relative;">
            <input class="colorpicker-hexInput" value="${this.rgba['rgb'[i]]}" spellcheck="false" style="font-size: 11px; color: rgb(51, 51, 51); width: 100%; border-radius: 2px; border: none; box-shadow: rgb(218, 218, 218) 0px 0px 0px 1px inset; height: 21px; text-align: center;">
            <span style="text-transform: uppercase; font-size: 11px; line-height: 11px; color: rgb(150, 150, 150); text-align: center; display: block; margin-top: 12px;">${'rgb'[i]}</span>
          </div>
        </div>`
    }
    return current_mode_html
  },
  setInputValue() {
    var hex = '#' + this.rgbToHex(this.HSBToRGB(this.hsb))
    var inputs = this.elem_wrap.getElementsByTagName('input')
    inputs[0].value = hex
    inputs[1].value = this.rgba['r']
    inputs[2].value = this.rgba['g']
    inputs[3].value = this.rgba['b']
  },
  setPosition(x, y) {
    var LEFT = parseInt(x - this.pancelLeft)
    var TOP = parseInt(y - this.pancelTop)

    this.pointLeft = Math.max(0, Math.min(LEFT, this.pancel_width))
    this.pointTop = Math.max(0, Math.min(TOP, this.pancel_height))

    util.css(this.elem_picker, {
      left: this.pointLeft + 'px',
      top: this.pointTop + 'px'
    })
    this.hsb.s = parseInt(100 * this.pointLeft / this.pancel_width)
    this.hsb.b = parseInt(100 * (this.pancel_height - this.pointTop) / this.pancel_height)

    this.setShowColor()
    this.setValue(this.rgba)
  },
  setBar: function(elem, x) {
    var elem_bar = elem.getElementsByTagName('div')[0]
    var rect = elem.getBoundingClientRect()
    var elem_width = elem.offsetWidth
    var X = Math.max(0, Math.min(x - rect.x, elem_width))

    if (elem_bar === this.elem_barPicker1) {
      util.css(elem_bar, {
        left: X + 'px'
      })
      this.hsb.h = parseInt(360 * X / elem_width)
    } else {
      util.css(elem_bar, {
        left: X + 'px'
      })
      this.rgba.a = X / elem_width
    }

    this.setPancelColor(this.hsb.h)
    this.setShowColor()
    this.setValue(this.rgba)
  },
  setPancelColor: function(h) {
    var rgb = this.HSBToRGB({ h: h, s: 100, b: 100 })

    util.css(this.elem_colorPancel, {
      background: 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + this.rgba.a + ')'
    })
  },
  setShowColor: function() {
    var rgb = this.HSBToRGB(this.hsb)

    this.rgba.r = rgb.r
    this.rgba.g = rgb.g
    this.rgba.b = rgb.b

    util.css(this.elem_showColor, {
      background: 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + this.rgba.a + ')'
    })
  },
  setValue: function(rgb) {
    var hex = '#' + this.rgbToHex(rgb)
    this.setInputValue()
    this.Opt.change(this.bindElem, hex)
  },
  setColorByInput: function(value, mode) {
    if (mode === 'hex') {
      value = value.slice(1)
      if (value.length === 3) {
        value = '#' + value[0] + value[0] + value[1] + value[1] + value[2] + value[2]
        this.hsb = this.hexToHsb(value)
      } else if (value.length === 6) {
        this.hsb = this.hexToHsb(value)
      }
    } else {
      var inputs = this.elem_wrap.getElementsByTagName('input')
      var rgb = {
        r: inputs[1].value ? parseInt(inputs[1].value) : 0,
        g: inputs[2].value ? parseInt(inputs[2].value) : 0,
        b: inputs[3].value ? parseInt(inputs[3].value) : 0
      }
      this.hsb = this.rgbToHsb(rgb)
    }
    this.changeViewByHsb()
    this.setInputValue()
  },
  changeViewByHsb: function() {
    this.pointLeft = parseInt(this.hsb.s * this.pancel_width / 100)
    this.pointTop = parseInt((100 - this.hsb.b) * this.pancel_height / 100)
    util.css(this.elem_picker, {
      left: this.pointLeft + 'px',
      top: this.pointTop + 'px'
    })

    this.setPancelColor(this.hsb.h)
    this.setShowColor()
    util.css(this.elem_barPicker1, {
      left: this.hsb.h / 360 * (this.elem_barPicker1.parentNode.offsetWidth) + 'px'
    })

    var hex = '#' + this.rgbToHex(this.HSBToRGB(this.hsb))
    this.Opt.change(this.bindElem, hex)
  },
  bindMove: function(elem, fn, bool) {
    var _this = this

    elem.addEventListener('mousedown', function(e) {
      _this.downX = e.pageX
      _this.downY = e.pageY
      bool ? fn.call(_this, _this.downX, _this.downY) : fn.call(_this, elem, _this.downX, _this.downY)

      document.addEventListener('mousemove', mousemove, false)
      function mousemove(e) {
        _this.moveX = e.pageX
        _this.moveY = e.pageY
        bool ? fn.call(_this, _this.moveX, _this.moveY) : fn.call(_this, elem, _this.moveX, _this.moveY)
        e.preventDefault()
      }
      document.addEventListener('mouseup', mouseup, false)
      function mouseup(e) {
        document.removeEventListener('mousemove', mousemove, false)
        document.removeEventListener('mouseup', mouseup, false)
      }
    }, false)
  },
  show: function() {
    util.css(this.elem_wrap, {
      'display': 'block'
    })
    this.Opt.open()
  },
  hide: function() {
    util.css(this.elem_wrap, {
      'display': 'none'
    })
    this.elem_wrap.remove()
    this.Opt.close()
  },
  HSBToRGB: function(hsb) {
    var rgb = {}
    var h = Math.round(hsb.h)
    var s = Math.round(hsb.s * 255 / 100)
    var v = Math.round(hsb.b * 255 / 100)

    if (s === 0) {
      rgb.r = rgb.g = rgb.b = v
    } else {
      var t1 = v
      var t2 = (255 - s) * v / 255
      var t3 = (t1 - t2) * (h % 60) / 60

      if (h === 360) h = 0

      if (h < 60) { rgb.r = t1; rgb.b = t2; rgb.g = t2 + t3 } else if (h < 120) { rgb.g = t1; rgb.b = t2; rgb.r = t1 - t3 } else if (h < 180) { rgb.g = t1; rgb.r = t2; rgb.b = t2 + t3 } else if (h < 240) { rgb.b = t1; rgb.r = t2; rgb.g = t1 - t3 } else if (h < 300) { rgb.b = t1; rgb.g = t2; rgb.r = t2 + t3 } else if (h < 360) { rgb.r = t1; rgb.g = t2; rgb.b = t1 - t3 } else { rgb.r = 0; rgb.g = 0; rgb.b = 0 }
    }

    return { r: Math.round(rgb.r), g: Math.round(rgb.g), b: Math.round(rgb.b) }
  },
  rgbToHex: function(rgb) {
    var hex = [
      rgb.r.toString(16),
      rgb.g.toString(16),
      rgb.b.toString(16)
    ]
    hex.map(function(str, i) {
      if (str.length === 1) {
        hex[i] = '0' + str
      }
    })

    return hex.join('')
  },
  hexToRgb: function(hex) {
    hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16)
    return { r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF) }
  },
  hexToHsb: function(hex) {
    return this.rgbToHsb(this.hexToRgb(hex))
  },
  rgbToHsb: function(rgb) {
    var hsb = { h: 0, s: 0, b: 0 }
    var min = Math.min(rgb.r, rgb.g, rgb.b)
    var max = Math.max(rgb.r, rgb.g, rgb.b)
    var delta = max - min
    hsb.b = max
    hsb.s = max !== 0 ? 255 * delta / max : 0
    if (hsb.s !== 0) {
      if (rgb.r === max) hsb.h = (rgb.g - rgb.b) / delta
      else if (rgb.g === max) hsb.h = 2 + (rgb.b - rgb.r) / delta
      else hsb.h = 4 + (rgb.r - rgb.g) / delta
    } else hsb.h = -1
    hsb.h *= 60
    if (hsb.h < 0) hsb.h += 360
    hsb.s *= 100 / 255
    hsb.b *= 100 / 255
    return hsb
  }
}

Colorpicker.create = function(opt) {
  return new Colorpicker(opt)
}

export default Colorpicker
